package com.dingreading.cloud.common.util;

import com.dingreading.cloud.common.base.R;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.*;
import java.util.*;

/**
 * 本地文件处理工具
 */
public class LocalFileUtil {

    public static final String baseUrl = "/home/www/DingSpaceOS/public/uploadimgs/";
    public static final String orderFormBaseDir = baseUrl + "mallpayimgs/";
    public static final String memberCastBaseDir = baseUrl + "membercash/";
    public static final String contractBaseDir = baseUrl + "contract/";
    public static final String followBaseDir = baseUrl + "follow/";
    public static final String payImgBaseDir = baseUrl + "payimgs/";

    /**
     * 上传文件到服务器
     */
    public static R<String> uploadFile(String baseDri, MultipartFile file) throws Exception {
        if (null == file) return R.fail("文件不能为空");
        boolean m = FileUtil.checkFileSize(file.getSize(), 30, "M");
        if (!m) return R.fail("文件大小不能超过30M");

        String fileName = getFileName(file);
        if (StringUtils.isBlank(fileName)) return R.fail("获取文件名失败");

        if (!fileName.contains(".jpg") && !fileName.contains(".jpeg") && !fileName.contains(".png") && !fileName.contains(".pdf"))
            return R.fail("请上传png,jpg,jpeg图片或pdf文件");

        String nowDateStr = DateUtil.getNowDateStr();
        String[] split = StringUtils.split(nowDateStr, "-");
        // linux文件路径
        String ymd = split[0] + "/" + split[1] + "/" + split[2] + "/";

        // 文件夹不存在则创建
        String dirPath = baseDri;
        List<String> newDirs = new ArrayList<>();
        File baseFile = new File(dirPath);
        if (!baseFile.exists()) {
            boolean mkdirs = baseFile.mkdirs();
            if (mkdirs)
                newDirs.add(dirPath);
        }
        for (int i = 0; i < split.length; i++) {
            dirPath = dirPath + split[i] + "/";
            File dir = new File(dirPath);
            if (!dir.exists()) {
                boolean mkdir = dir.mkdir();
                if (mkdir)
                    newDirs.add(dirPath);
            }
        }
        // 将要保存的文件加入更改权限的列表中
        String newFilePath = baseDri + ymd + fileName;
        newDirs.add(newFilePath);

        //保存照片到指定路径
        File newFile = new File(newFilePath);
        file.transferTo(newFile);

        // 如果有新建的文件夹，重新设置文件夹的所有者和组
        if (CollectionUtils.isNotEmpty(newDirs)) {
            String owner = "www";
            String group = "www";
            changePermission(newDirs, owner, group);
        }

        return R.ok(ymd + fileName);
    }

    /**
     * 上传图片到服务器
     */
    public static R<String> uploadImg(String baseDri, MultipartFile file) throws Exception {
        if (null == file) return R.fail("图片不能为空");
        boolean m = FileUtil.checkFileSize(file.getSize(), 10, "M");
        if (!m) return R.fail("图片大小不能超过10M");

        String fileName = getFileName(file);
        if (StringUtils.isBlank(fileName)) return R.fail("获取图片名失败");

        if (!fileName.contains(".jpg") && !fileName.contains(".jpeg") && !fileName.contains(".png"))
            return R.fail("请上传png,jpg,jpeg格式的图片");

        String nowDateStr = DateUtil.getNowDateStr();
        String[] split = StringUtils.split(nowDateStr, "-");
        // linux文件路径
        String ymd = split[0] + "/" + split[1] + "/" + split[2] + "/";

        // 文件夹不存在则创建
        String dirPath = baseDri;
        List<String> newDirs = new ArrayList<>();
        File baseFile = new File(dirPath);
        if (!baseFile.exists()) {
            boolean mkdirs = baseFile.mkdirs();
            if (mkdirs)
                newDirs.add(dirPath);
        }
        for (int i = 0; i < split.length; i++) {
            dirPath = dirPath + split[i] + "/";
            File dir = new File(dirPath);
            if (!dir.exists()) {
                boolean mkdir = dir.mkdir();
                if (mkdir)
                    newDirs.add(dirPath);
            }
        }
        // 将要保存的文件加入更改权限的列表中
        String newFilePath = baseDri + ymd + fileName;
        newDirs.add(newFilePath);

        //保存照片到指定路径
        File newFile = new File(newFilePath);
        file.transferTo(newFile);

        // 如果有新建的文件夹，重新设置文件夹的所有者和组
        if (CollectionUtils.isNotEmpty(newDirs)) {
            String owner = "www";
            String group = "www";
            changePermission(newDirs, owner, group);
        }

        return R.ok(ymd + fileName);
    }

    /**
     * 删除本地图片
     */
    public static final void deleteImg(String dirPath, String img) {
        if (StringUtils.isNotBlank(img)) {
            File file = new File(dirPath + img);
            if (file.exists())
                file.delete();
        }
    }

    /**
     * 删除本地图片集合
     */
    public static final void deleteImgList(String dirPath, List<String> imgList) {
        if (CollectionUtils.isNotEmpty(imgList)) {
            for (String url : imgList) {
                File file = new File(dirPath + url);
                if (file.exists())
                    file.delete();
            }
        }
    }

    /**
     * 获取新的文件名
     */
    public static final String getFileName(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
        return UUID.randomUUID().toString().toUpperCase().replace("-", "") + substring;
    }

    /**
     * 开始更改文件夹所有者和组
     */
    public static final void changePermission(List<String> newDirs, String owner, String group) {
        //设置文件和文件夹的权限
        boolean supportPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
        if (!supportPosix) {
            System.out.println("Your OS does not support posix.");
        } else {
            // 将要设置的权限：用户，组，以及三组读/写/执行的权限
            Set<PosixFilePermission> perms = new HashSet<>();
            perms.add(PosixFilePermission.OWNER_READ);
            perms.add(PosixFilePermission.OWNER_WRITE);
            perms.add(PosixFilePermission.OWNER_EXECUTE);
            perms.add(PosixFilePermission.GROUP_READ);
            perms.add(PosixFilePermission.GROUP_WRITE);
            perms.add(PosixFilePermission.GROUP_EXECUTE);
            perms.add(PosixFilePermission.OTHERS_READ);
            perms.add(PosixFilePermission.OTHERS_WRITE);
            perms.add(PosixFilePermission.OTHERS_EXECUTE);
            for (int i = 0; i < newDirs.size(); i++) {
                String newDir = newDirs.get(i);
                setPermission(newDir, owner, group, perms);
            }
        }
    }

    /**
     * 修改文件夹的所有者和组
     */
    private static final void setPermission(String pathStr, String owner, String group, Set<PosixFilePermission> perms) {
        Path path = Paths.get(pathStr);
        if (!Files.exists(path)) {
            System.out.println(pathStr + " not exists!");
            return;
        }
        try {
//            System.out.format("Before, %s ", pathStr);
//            readTargetPermission(path);
            // 设置permission，相当于linux命令chmod
            Files.setPosixFilePermissions(path, perms);
            // 设置用户和组，相当于linux命令chown
            // 要保证用户和组存在，否则lookupService会抛UserPrincipalNotFoundException
            UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService();
            GroupPrincipal groupPrincipal = lookupService.lookupPrincipalByGroupName(group);
            UserPrincipal userPrincipal = lookupService.lookupPrincipalByName(owner);
            PosixFileAttributeView view = Files.getFileAttributeView(path, PosixFileAttributeView.class);
            view.setGroup(groupPrincipal);
            view.setOwner(userPrincipal);
//            System.out.format("After, %s ", pathStr);
//            readTargetPermission(path);
        } catch (IOException e) {
            if (e instanceof UserPrincipalNotFoundException) {
                System.out.format("group %s or owner %s not exist%n", group, owner);
            }
            e.printStackTrace();
        }
    }

    /**
     * print current permission of folder/file
     */
    private void readTargetPermission(Path path) throws IOException {
        Set filePermissions = Files.readAttributes(path, PosixFileAttributes.class).permissions();
        GroupPrincipal fileGroup = Files.readAttributes(path, PosixFileAttributes.class).group();
        UserPrincipal fileOwner = Files.readAttributes(path, PosixFileAttributes.class).owner();
        System.out.format("permissions: %s, user: %s, group: %s%n", PosixFilePermissions.toString(filePermissions), fileOwner, fileGroup);
    }
}
